package com.asa.hutils;

import java.util.ArrayList;
import java.util.List;

import com.asa.utils.Calculate;

/**
 * 求矩阵的逆
 * @author Administrator
 *
 */
public class Ni {
	
	/**
	 * 参数必须是下面这种已经配好增广矩阵的形式哟
	 * double a[][] = {{1,6,9,1,0,0},{4,2,7,0,1,0},{8,5,3,0,0,1}};
	 * @param a
	 */
	public static double[][] getNi(double a[][]) {

		//double a[][] = {{1,6,9,1,0,0},{4,2,7,0,1,0},{8,5,3,0,0,1}};
		int h=0,l=0;
		int flage=1;
		int n = a.length;
		////System.out.println("请输入原矩阵:");
		
//		for(h=0;h<n;h++){  //添单位阵使之为（A E）矩阵。
//		    for(l=n;l<2*n;l++)
//			{
//		    	if(l==n+h) a[h][l]=1;
//		    	else a[h][l]=0;
//			}
//		}    
		//System.out.println();
		////System.out.println("原矩阵的增广矩阵为:");
		for(h=0;h<n;h++)  //输出A的增广矩阵。
		{
			for(l=0;l<2*n;l++)
//			System.out.print("\t"+a[h][l]);
			System.out.print("");
		}
//		//System.out.println();
//		//System.out.println(h+"        "+l);
//		a[h-1][l-1]=
				fap(a,n,2*n);
//		for(h=0;h<n;h++)  //判断A是否存在逆矩阵。
//		{
//			flage*=a[h][h];
//		}
//	    if(flage==0)
//		{
//			//System.out.println("该矩阵不可逆!");
//		    return null;
//		}
//		//System.out.println(a[h-1][l-1]);


//		a[h-1][l-1]=
				f(a,n);
		
//		//System.out.println(a[h-1][l-1]);

//		a[h-1][l-1]=
				p(a,n);
//		//System.out.println(a[h-1][l-1]);
//		//System.out.println();
//		//System.out.println("原矩阵的逆矩阵为:");
//	    for(h=0;h<n;h++)  //输出A的逆矩阵。
//		{
//			for(l=n;l<2*n;l++)
//			System.out.print("\t"+a[h][l]);
//			//System.out.println();
//		}
	    return a;
	}

	public static double fap(double a[][], int n, int m) // 划（A E）矩阵为阶梯型。
	{
		int i = 0, j = 0, t = 0, k;
		double temp;
		for (k = i = 0; i < n && k < m; k++)// 判断A矩阵对角线上的值是否为0。
		{
			if (a[i][k] == 0) // 如果为0，则与后面不为0的行交换。
				for (j = i; j < n; j++) {
					if (j < n) {
						for (t = k; t < m; t++) {
							temp = a[i][t];
							a[i][t] = a[j][t];
							a[j][t] = temp;
						}
					}
				}

			if (a[i][k] != 0) // 如果不为0，则划（A E）为阶梯型。
			{
				for (j = i + 1; j < n; j++) {
					if (a[j][k] != 0) {
						temp = a[j][k] / a[i][k];
						for (t = i; t < m; t++)
							a[j][t] = a[j][t] - a[i][t] * temp;
					}
				}
				i++;
			}
		}
		return a[j-1][t-1];
	}

	public static double f(double a[][], int n)// 划A矩阵为对角阵。
	{
		int i, j = 0, k, t = 0;
		double temp;
		for (k = i = n - 1; i > 0 && k >= 0; k--) {
			if (i - 1 >= 0) {
				if (a[i - 1][k] != 0) {
					for (j = i - 1; j >= 0 && a[i][k] != 0; j--) {
						temp = a[j][k] / a[i][k];
						for (t = 2 * n - 1; t >= 0; t--)
							a[j][t] = a[j][t] - a[i][t] * temp;
					}
				}
				i--;
			}
		}
		return a[j+1][t+1];
	}
	
	
	public static double p(double a[][],int n)//划A矩阵为单位阵。
	{
		int i,j,k,t=0;double temp;
		for(i=k=0;i<n&&k<n; )
		{
			temp=a[i][k];
			if(a[i][k]!=1&&a[i][k]!=0)
			{
				for(j=i;j<n;j++)
					for(t=k;t<2*n;t++)
						a[j][t]=a[j][t]/temp;
			}
			i++;
			k++;
		}
		////System.out.println();
	   // //System.out.println("原矩阵行变换之后的矩阵为:");
		for(j=0;j<n;j++)
		{
			for(t=0;t<2*n;t++)
//	        System.out.print("\t"+a[j][t]);
		    System.out.print("");
		}
		return a[j-1][t-1];
	}

	/*****************************************************************************************************************************************************/
	
	
	public static double[][] ni2(double a[][],int n)//用伴随矩阵求矩阵的逆		
	{
		double hangleishivalue = hangleishivalue(a);
		if (hangleishivalue==0) {
			return null;
		}
		double[][] bansui = bansuijuzhen(a, n);
		for (int i = 0; i < bansui.length; i++) {
			for (int j = 0; j < bansui.length; j++) {
				bansui[i][j] = bansui[i][j]/hangleishivalue;
			}
		}
		

		
		return bansui;
	}
	
	
	
	
	
	
	
	
	
	
	
	public static double[][] bansuijuzhen(double a[][],int n)//计算伴随矩阵 默认就是nXn的吧，以后在做nXm的
	{
		double[][] bansui = new double[a.length][a.length];
		for (int i = 0; i < a.length; i++) {
			
			for (int j = 0; j < a[i].length; j++) {
				bansui[i][j] = daishuyuzixiang(a,i,j);
			}
			
		}

		
		return bansui;
	}

	/**
	 * 计算代数余子式的值
	 * @param a 行列式
	 * @param i 行
	 * @param j	列
	 * @return
	 */
	public static double daishuyuzixiang(double[][] a, int i, int j) {//代数余子式
		// TODO Auto-generated method stub
		
		double[][] a_ = new double[a.length-1][a.length-1];
		
		for (int k = 0; k < a.length; k++) {
			for (int l = 0; l < a.length; l++) {
				
				if (k==i||j==l) {
					continue;
				}
				int indexk = k;
				int indexl = l;
				if (indexk>i) {
					indexk = indexk-1;
				}
				if (indexl>j) {
					indexl = indexl-1;
				}
				
				a_[indexk][indexl] = a[k][l];

			}
		}
		
		return hangleishivalue(a_);
	}

	public static double hangleishivalue(double[][] a_) {//计算行列式的值
		// TODO Auto-generated method stub
		
		double result = 0;
		
		
		int n = a_.length;
		int[] A = new int[n];

		List<int[]> listzuhe = print_permutation(n, A, 0,null);
		
		
		
		
		for (int i = 0; i < listzuhe.size(); i++) {
			double chengzi = 1;

			for (int j = 0; j < listzuhe.get(i).length; j++) {
//				System.out.println(j);
				chengzi = chengzi*a_[j][listzuhe.get(i)[j]-1];
	
			}
			double τ = τ(listzuhe.get(i));
//			System.out.println(chengzi+"      "+τ);
			result += τ*chengzi;

			
		}

		
		return result;
	}
	
	
	
	
	public static double τ(int[] j) {//行列式求值中，那个τ，等等，好像没必要求,还是要计算，我脑残了
		
		int count = 0;
		
		//行列式的值计算，这个代码没有问题，我很肯定
//		System.out.println("我怀疑τ算得有问题");
//		for (int i = 0; i < j.length; i++) {
//			System.out.print(j[i]+"  ");
//		}
//		System.out.println("我怀疑τ算得有问题============end");
		
		for (int i = 0; i < j.length; i++) {
			for (int k = i; k < j.length; k++) {
				if (j[i]>j[k]) {
					count++;
				}
			}
		}
//		System.out.println(count);
		if (count%2==1) {
			return -1;

		}else {
			return 1;
		}
		
		
	}
	
	
	
	
	public static List<int[]> print_permutation(int n, int A[], int cur,List<int[]> as){ // cur == current
		if (as==null) {
			as = new ArrayList<>();
		}
		  if(cur == n) {
			int[] zuhe = new int[n]; 
		    for(int i=0; i<n; i++) {
//		    	System.out.print(A[i]+"  ");
		    	zuhe[i] = A[i];
		    }
		    as.add(zuhe);
//	    	System.out.println();
		  }
		  else for(int i=1; i<=n; i++){
		    int ok = 1;
		    for (int j=0; j<cur; j++) if(A[j] == i) {ok = 0; break;} //再次强调，静态查错，不经大脑的写错变量用这种方式是最容易查出来的
		    if(ok==1) {
		      A[cur] = i;
		      print_permutation(n, A, cur+1,as);
		    }
		  }
		  return as;
		}
	
	
	public static void main(String[] args) throws Exception {
		
		
//		int n;
//		  //scanf("%d",&n);
//		  n = 4;
//			int[] A = new int[n];
//
//		  List<int[]> print_permutation = print_permutation(n, A, 0,null);
//		  System.out.println("........................................");
//		  
//		  for (int i = 0; i < print_permutation.size(); i++) {
//			  for (int j = 0; j < print_permutation.get(i).length; j++) {
//				System.out.print(print_permutation.get(i)[j]+"    ");
//			}
//			  System.out.println();
//			
//		}
		
		
		
//		double[][] a_ = {{1,2},{-1,-3}};
		
//		double[][] a_ = {{2,2,3},{1,-1,0},{-1,2,1}};
//		double hangleishivalue = hangleishivalue(a_ );
//		System.out.println(hangleishivalue);
//		
//		
//		double[][] ni2 = ni2(a_, 2);
//		
//		for (int i = 0; i < ni2.length; i++) {
//			for (int j = 0; j < ni2[i].length; j++) {
//				System.out.print(ni2[i][j]+"  ");
//			}
//			System.out.println();
//		}
//		double[][] chenfa = MathHUtils.chenfa(a_, MathHUtils.zhuanzhi(ni2));
//		for (int i = 0; i < chenfa.length; i++) {
//			for (int j = 0; j < chenfa[i].length; j++) {
//				System.out.print(chenfa[i][j]+"  ");
//			}
//			System.out.println();
//		}
//		
//		double[][] juzhengni = MathHUtils.juzhengni(a_);
//		System.out.println("============================");
//		for (int i = 0; i < juzhengni.length; i++) {
//			for (int j = 0; j < juzhengni[i].length; j++) {
//				System.out.print(juzhengni[i][j]+"  ");
//			}
//			System.out.println();
//		}
//		chenfa = MathHUtils.chenfa(a_, juzhengni);
//		for (int i = 0; i < chenfa.length; i++) {
//			for (int j = 0; j < chenfa[i].length; j++) {
//				System.out.print(chenfa[i][j]+"  ");
//			}
//			System.out.println();
//		}
		
		
		
		int[] j = new int[] {3,1,4,2};
		double τ = τ(j);
		System.out.println(τ);
		
	}
	
	

}
